//
// Created by QU on 2024/1/16.
//

// c++ standard library
#include <cassert>
#include <iostream>
#include <list>
#include <vector>
#include <map>
#include <set>

// boost library
#include <boost/pool/pool.hpp>

// using namespace
using std::cin, std::cout, std::endl;
using boost::pool;

// pool库概述:
// boost.pool基于简单的分隔存储的思想实现了一个快速, 紧凑的内存存储池. 不仅能够管理大量的对象, 还可以用作STL的内存分配器.
// 从某种程度来说, 他近似一个垃圾回收的机制, 在需要大量分配/释放小对象时效率很高, 而且完全不用考虑delete.

// pool包含4个组成部分: 最简单的pool;  分配类实例的object_pool; 单间内存池singleton_pool; 可用于标准库的pool_alloc. (只介绍前3个)

int main(int argc, char const *argv[]){
    // pool 是最简单的内存池类, 他可以返回一个简单数据类型 {POD} (Plain Of Data) 的内存指针.


    // pool的模版类型参数UserAllocator是一个用户定义的内存分配器, 他实现了特定的分配算法,
    // 通常可以使用默认的分配器default_user_allocator_new_delete, 它使用的是new[]和delete[]分配内存空间.

    // pool的构造函数可以接受一个size_type类型的整数requested_size, 指示每次分配的内存大小(而不是内存池的总大小),
    // 你可以使用get_requested_size获得这个值.
    // pool会根据需要自动的向系统申请需要使用或者归还所需的内存, 析构的时候, pool将释放它拥有的所有的内存.
    // pool的malloc函数和ordered_malloc的行为类似C语言的malloc(), 用void*指针返回内存池中分配的内存块, 内存大小为构造函数中指定的requested_size.
    // 如果分配失败, 返回0(空指针), 不会抛出异常.

    // malloc()返回内存池中的任意一个内存块, \
    // ordered_malloc()在分配的同时合并空闲块链表, ordered_malloc()带有参数的形式还可以连续分配n块内存.
    // 你可以使用is_from()函数测试分配后的内存块是否是这个内存池分配出去的.

    // 和malloc()对应的是free()函数. free()用来手动释放之前分配出去的内存块, 这个内存块必须是从这个内存池分配出去的(is_form(chunk) == true)
    // 一般情况下, 不应该调用free(), 除非你认为内存池的空间已经不足, 必须释放已经分配的内存.

    // release_memory()让内存池释放所有没有被分配的内存, 已经分配的内存不受影响.
    // purge_memory()强制释放pool持有的所有内存.

    // 注意!! ::
    // boost.pool只能使用于标准类型(通用类型), 不能将他用在复杂的类或者对象中, 因为他不会主动调用类的析构函数.
    // 如果想要主动调用析构函数, 请使用object_pool.

    boost::pool<> p1 = boost::pool(sizeof(int));        // 一个可以内配int的内存
    int * pInt = static_cast<int *>(p1.malloc());
    assert(p1.is_from(pInt));

    p1.free(pInt);

    void * returned_error = nullptr;
    for (int i = 0; i < 100; ++i) {
        returned_error = p1.ordered_malloc(10);
        // 因为malloc的时候不会返回异常. 所以实际编写代码的时候都需要检查malloc返回的指针.  虽然说这种情况比较少出现.
        if (!returned_error){
            cout << "pool Memory malloc error." << endl;
            break;
        }
        if ( i % 10 == 0)
        cout << i / 10  << ' ';
    }
    cout << endl;

}
